import { createPromise } from "./promise"
import path from "path"
// 拷贝函数 是否包括函数拷贝
function func_copy<T>(obj: T | any, bFunc = false): T {
    var out: any;
    if (obj instanceof Array) {
        out = [];
        // 数组这里就
        for (let i = 0; i < obj.length; i++) {
            out[i] = func_copy(obj[i], bFunc);
        }
    }
    else if (obj instanceof Buffer) {
        // buffer 这里就不拷贝算了
        out = Buffer.from(obj);
    }
    else if (obj instanceof Date) {
        out = new Date(obj);
    }
    else if (typeof obj == 'object') {
        out = {};
        for (var key in obj) {
            if (key == 'clone' || key == 'global') {
                continue;
            }
            if (typeof obj[key] == 'function' && !bFunc) {
                continue;
            }
            if (obj[key] == null) { out[key] = null; }
            else out[key] = func_copy(obj[key], false);
        }
    }
    else {
        out = obj;
    }

    return <T>out;
}

function func_attach(dst: any, src: any) {
    if (!dst || !src) return;

    for (var key in src) {
        dst[key] = Util.copy(src[key]);
    }

    return dst;
}


function promise_setInterval(callback: () => Promise<any>, time: number): { stop: () => void };
function promise_setInterval(name: string, callback: () => Promise<any>, time: number): { stop: () => void };
function promise_setInterval(...args: any[]) {
    let [name, callback, time] = args;
    if (typeof name != 'string') {
        name = '';
        callback = args[0];
        time = args[1];
    }

    let handle: NodeJS.Timeout;
    function update() {
        createPromise(callback()).finally(function () {
            if (handle) {
                if (handle.refresh) {
                    handle.refresh();
                }
                else {
                    handle = setTimeout(update, time);
                }
            }
        })
    }

    handle = setTimeout(update, time);
    (handle as any)['name'] = name;

    return {
        stop: function () {
            clearTimeout(handle);
        }
    }

}


function getCallerFileNameAndLine() {
    function getException() {
        try {
            throw Error('');
        } catch (err) {
            return err;
        }
    }

    const err = getException();

    const stack = err.stack;
    const stackArr = stack.split('\n');
    let callerLogIndex = 0;
    for (let i = 0; i < stackArr.length; i++) {
        if (stackArr[i].indexOf('makeError') > 0 && i + 1 < stackArr.length) {
            callerLogIndex = i + 1;
            break;
        }
    }

    if (callerLogIndex !== 0) {
        const callerStackLine = stackArr[callerLogIndex] as string;
        let list = callerStackLine.split(/\(|\)/)
        if (list[1] && list[1].length > 0) {
            return list[1].replace(process.cwd(), '').replace(/\\/g, "/").replace('/', '')
        }
        else {
            return `[${callerStackLine.substring(callerStackLine.lastIndexOf(path.sep) + 1, callerStackLine.lastIndexOf(':'))}]`;
        }
    } else {
        return '[-]';
    }
}
export var Util = {
    copy: func_copy,
    attach: func_attach,
    setInterval: promise_setInterval,
    makeError: function (code: number, msg: string) {
        return { code: code, errMsg: msg, __line__: getCallerFileNameAndLine() }
    }
}
